package homework00110;

import java.util.function.IntConsumer;

class FizzBuzz {
    private int n;
    private int i;
    private volatile int state=0;

    public FizzBuzz(int n) {
        this.n = n;
        this.i=1;
    }

    // printFizz.run() outputs "fizz".
    public void fizz(Runnable printFizz) throws InterruptedException {
        synchronized(this){
            while(i <= n){
                if(state!=1){
                	wait();
                }else{
                	printFizz.run();
                    i++;
                    state=0;
                    notifyAll();
                }
            }
        }
    }

    // printBuzz.run() outputs "buzz".
    public void buzz(Runnable printBuzz) throws InterruptedException {
        synchronized(this){
            while(i <= n){
                if(state!=2){
                	wait();
                    
                }else{
                	printBuzz.run();
                    i++;
                    state=0;
                    notifyAll();
                }
            }
        }
    }

    // printFizzBuzz.run() outputs "fizzbuzz".
    public void fizzbuzz(Runnable printFizzBuzz) throws InterruptedException {
        synchronized(this){
            while(i <= n){
                if(state!=3){
                	wait();
                    
                }else{
                	printFizzBuzz.run();
                    i++;
                    state=0;
                    notifyAll();
                }
            }
        }
    }

    // printNumber.accept(x) outputs "x", where x is an integer.
    public void number(IntConsumer printNumber) throws InterruptedException {
        synchronized(this){
            while(i <= n){
                if(state!=0){
                	wait();
                }else{
                	if(i%3!=0&&i%5!=0){
                		printNumber.accept(i);
                        i++;
                        state=0;
                        notifyAll();
                	}else if(i%3==0&&i%5!=0){
                    	state=1;
                    	notifyAll();
                    }else if(i%3!=0&&i%5==0){
                    	state=2;
                    	notifyAll();
                    }else{
                    	state=3;
                    	notifyAll();
                    }
                }
            }
        }
    }
}